﻿using FANUC.DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;

namespace FANUC.Controllers
{
    public class RobotCurrentInfoController : ApiController
    {
        private FANUCDB db = new FANUCDB();

        private decimal GetRunningRatioByRobotId(int id)
        {
            //当天00:00:00
            DateTime today0 = System.DateTime.Now.Date;
            //此机器人当天第一个状态;-1:default,1:PowerOff,2:Fault,3:Ready,4:Running
            int firstState, lastState = -1;
            //第一次发生事件改变的时间点
            DateTime todayFirstChangeTime;
            //当前时间点
            DateTime now = System.DateTime.Now;

            //此机器人当天0点开始第一个变化记录，FANUC会在0点插入一条最新机器人的状态
            var todayFirstChangeRecord = db.Robot_State_Change_History.Where(a => a.ChangeDateTime >= today0 && a.Robot_ID == id).OrderBy(a => a.ChangeDateTime).FirstOrDefault();
            if (todayFirstChangeRecord == null)
            {
                todayFirstChangeTime = today0;
                firstState = 1;
            }
            else
            {
                todayFirstChangeTime = todayFirstChangeRecord.ChangeDateTime;
                firstState = todayFirstChangeRecord.Changed_State_Type;
            }

            List<Robot_State_Change_History> allStateChangeRecords = db.Robot_State_Change_History.Where(a => a.ChangeDateTime > todayFirstChangeTime && a.Robot_ID == id).ToList();
            //按状态合计各状态时间(分钟)
            var stateGroupSumByState = from a in allStateChangeRecords group a by new { a.Original_State_Type } into grp select new { grp.Key.Original_State_Type, TotalMinutes = grp.Sum(a => a.Period) };

            //获取当天最后一个机器人状态
            var todayLastChangeRecord = db.Robot_State_Change_History.Where(a => a.ChangeDateTime > today0 && a.Robot_ID == id).OrderByDescending(a => a.ChangeDateTime).FirstOrDefault();
            DateTime lastChangeTime;
            if (todayLastChangeRecord == null)
            {
                lastState = 1;
                lastChangeTime = now;
            }
            else
            {
                lastState = todayLastChangeRecord.Changed_State_Type;
                lastChangeTime = todayLastChangeRecord.ChangeDateTime;
            }
            var todayTotalRunningSum = stateGroupSumByState.Where(a => a.Original_State_Type == 4).FirstOrDefault();
            int todayTotalRunningMinutes = Convert.ToInt32(todayTotalRunningSum == null ? 0 : todayTotalRunningSum.TotalMinutes) + (lastState == 4 ? Convert.ToInt32((now - lastChangeTime).TotalMinutes) : 0);
            int todayTotalMinutes = Convert.ToInt32((now - today0).TotalMinutes);
            decimal runningRatio = Convert.ToDecimal(todayTotalRunningMinutes) / todayTotalMinutes;
            return Decimal.Round(runningRatio, 4);
        }
        /// <summary>
        /// GET: api/ApiAlarmHistory/1
        /// </summary>
        /// <returns>AlarmHistoryDTO</returns>
        [ResponseType(typeof(List<RobotInfoDto>))]
        public IHttpActionResult Get()
        {
            #region Test
            if (Helper.IsTest)
            {
                List<RobotInfoDto> testData = new List<RobotInfoDto>();
                for (int i = 0; i < 15; i++)
                {
                    RobotInfoDto robotInfo = new RobotInfoDto();
                    robotInfo.RobotId = i + 1;
                    robotInfo.Robot_YH_NO = "AR1258" + i.ToString();
                    robotInfo.Output = 1000 + i * 10;
                    robotInfo.RunningRatio = 70.5M + i;
                    robotInfo.State = i % 2;
                    testData.Add(robotInfo);
                }
                return Ok(testData);
            }
            #endregion
            var robots = db.Robot.ToList();
            List<RobotInfoDto> data = new List<RobotInfoDto>();
            DateTime today = System.DateTime.Now.Date;
            foreach (var robot in robots)
            {
                RobotInfoDto robotInfo = new RobotInfoDto();
                robotInfo.RobotId = robot.ID;
                robotInfo.Robot_YH_NO = robot.YH_No;
                switch (robot.Robot_Type.Type)
                {
                    case "Arc Welding":
                        robotInfo.Output = db.Part_Unit.Where(a => a.Robot_ID == robot.ID && a.Start_Time >= today).Count();
                        break;
                    case "Spot Welding":
                        robotInfo.Output = db.Spot_Part_Unit.Where(a => a.Robot_ID == robot.ID && a.Start_Time >= today).Count();
                        break;
                    case "Seal":
                        robotInfo.Output = db.Seal_Part_Unit.Where(a => a.Robot_ID == robot.ID && a.Start_Time >= today).Count();
                        break;
                    case "Press":
                        robotInfo.Output = db.Press_Part_Unit.Where(a => a.Robot_ID == robot.ID && a.Start_Time >= today).Count();
                        break;
                    case "Polish":
                        robotInfo.Output = db.Polish_Part_Unit.Where(a => a.Robot_ID == robot.ID && a.Start_Time >= today).Count();
                        break;
                    default:
                        robotInfo.Output = 0;
                        break;
                }

                robotInfo.RunningRatio = GetRunningRatioByRobotId(robot.ID);
                robotInfo.State = robot.Current_State;
                data.Add(robotInfo);
            }

            return Ok(data);
        }

        /// <summary>
        /// GET: api/ApiAlarmHistory/1
        /// </summary>
        /// <param name="id">Robot.ID</param>
        /// <returns>AlarmHistoryDTO</returns>
        [ResponseType(typeof(RobotInfoDto))]
        public IHttpActionResult Get(int id)
        {
            #region Test

            if (Helper.IsTest)
            {
                RobotInfoDto testData = new RobotInfoDto();
                testData.Robot_YH_NO = "AR12580";
                testData.Output = 1000;
                testData.RunningRatio = 70.5M;
                testData.State = 1;
                return Ok(testData);
            }
            #endregion
            var robot = db.Robot.Where(a => a.ID == id).FirstOrDefault();
            if (robot != null)
            {
                RobotInfoDto noData = new RobotInfoDto();
                noData.Robot_YH_NO = "";
                noData.Output = 0;
                noData.RunningRatio = 0;
                noData.State = 0;
                return Ok(noData);
            }
            DateTime today = System.DateTime.Now.Date;
            RobotInfoDto data = new RobotInfoDto();
            data.RobotId = id;
            data.Robot_YH_NO = robot.YH_No;
            data.Output = db.Part_Unit.Where(a => a.Robot_ID == robot.ID && a.Start_Time >= today).Count();
            data.RunningRatio = GetRunningRatioByRobotId(robot.ID);
            data.State = robot.Current_State;
            return Ok(data);
        }

        /// <summary>
        /// GET: api/ApiAlarmHistory/?id=Robot_YH_No&pageNumber=2&pageSize=10
        /// </summary>
        /// <param name="id">Robot_YH_No</param>
        /// <param name="pageNumber">Page Number</param>
        /// <param name="pageSize">Page Size</param>
        /// <returns></returns>
        [ResponseType(typeof(AlarmHistoryDtoOut))]
        public IHttpActionResult Get(int id, int pageNumber, int pageSize)
        {
            var alarms = db.Current_Alarm.Where(a => a.Robot_ID == id).OrderByDescending(o => o.Time).Skip(pageNumber).Take(pageSize).ToList();
            if (alarms.Count <= 0)
            {
                return NotFound();
            }
            AutoMapper.Mapper.Initialize(cfg => cfg.CreateMap<Alarm_History, AlarmRecordDTO>().ForMember(dest => dest.Robot_YH_No, src => src.MapFrom(s => s.Robot.YH_No)));
            List<AlarmRecordDTO> alarmsDTO = AutoMapper.Mapper.Map<List<AlarmRecordDTO>>(alarms);
            AlarmHistoryDtoOut data = new AlarmHistoryDtoOut();
            data.AlarmRecords = alarmsDTO;

            return Ok(data);
        }

        [ApiExplorerSettings(IgnoreApi = true)]
        public string Options()
        {
            return null;
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
